package nl.windgazer.arachne.components;

import org.apache.tapestry5.Asset;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.AfterRenderTemplate;
import org.apache.tapestry5.annotations.BeforeRenderTemplate;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.javascript.InitializationPriority;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;

/**
 * This Component adds a flash-file (.swf) to the page. This Component will
 * add the required JavaScript-Library and code as well as a 'placeholder' DIV
 * to the page. The content of this Component is what appears in this
 * 'placeholder' and will be shown to a user when his/her Flash-plugin is lower
 * than the required version, or non-existent. It will also be shown to a user
 * who has JavaScript disabled, as well as to search-engine crawlers.
 * This Component makes use of swfobject (http://blog.deconcept.com/swfobject/)
 * which is embedded in the jar as an Asset.
 *
 * @author mreuring
 */
@SupportsInformalParameters
public class Flash {

	//Injects and Persists

	@Inject
	private Request _req;

	@Inject
	private JavaScriptSupport _jss;

    @Inject
    private ComponentResources _cr;

    @Inject
    @Path("swfobject.js")
    private Asset swfobject;

	
	//Properties and Parameters

	private static final String DEFAULT_ELEMENT = "div";

    /**
     * HREF to the flash-file, relative to the root or as a fully verified URL (starting with http(s)://...).
     */
    @Parameter(required = true, defaultPrefix = "literal")
    private String href;

    /**
     * The width of the flash-movie.
     */
    @Parameter(required = true, defaultPrefix = "literal")
    private int width;

    /**
     * The height of the flash-movie.
     */
    @Parameter(required = true, defaultPrefix = "literal")
    private int height;

    /**
     * The required plugin-version to run this movie.
     */
    @Parameter(required = true, defaultPrefix = "literal")
    private String version;

    /**
     * The background-color for this movie.
     */
    @Parameter(required = true, defaultPrefix = "literal")
    private String background;

    /**
     * If this flash-movie needs to be displayed with transparency,
     * or have html on top of it, set transparent to true.
     */
    @Parameter(defaultPrefix = "literal")
    private boolean transparent = false;

    /**
     * A semicolon-separated key=value pair list that will be converted to
     * so.addParam(key, value);
     */
    @Parameter(defaultPrefix = "literal")
    private String params = null;

    /**
     * A semicolon-separated key=value pair list that will be converted to
     * so.addVariable(key, value);
     */
    @Parameter(defaultPrefix = "literal")
    private String vars = null;

    //Components

	//Events

    /**
     * Add the required JavaScript library to the page.
     */
    @SuppressWarnings("unused")
    @SetupRender
    private void setup()
    {
    	_jss.importJavaScriptLibrary(swfobject);
    	//Call this initializer 'early' to help with other, less dynamic, replacements being calculated correctly.
    	_jss.addInitializerCall(InitializationPriority.EARLY ,"createNewSWFObject", new JSONObject(
    													"href", getHref()
    													, "targetId", _cr.getId()
    													, "width", new Integer(width).toString()
    													, "height", new Integer(height).toString()
    													, "version", version
    													, "bg", background
    													, "wmode", new Boolean(transparent).toString()
    													, "params", params
    													, "vars", vars)
    	);
    }

    /**
     * Render the original element and its' contents, adding a unique id for later replacement by JS-code.
     * This method preserves any 'informal' parameters except id, which is generated and used for initialization
     * of SWFObject, replacing the original content with a flash-movie.
     * @param writer
     */
    @SuppressWarnings("unused")
	@BeforeRenderTemplate
    private void renderInformalElement(MarkupWriter writer) {
		Element informal = writer.element(_cr.getElementName(DEFAULT_ELEMENT)); //Create an element with the found element-name, or if that was a component, use default (div).
	    informal.attribute("id", _cr.getId()); //Render a unique id before informal parameters might override it...
	    _cr.renderInformalParameters(writer); //Render informal parmaters defined on the element in the template...
    }

    /**
     * Cleanup for generated content.
     * @param writer
     */
    @SuppressWarnings("unused")
	@AfterRenderTemplate
    private void closeInformalElement(MarkupWriter writer) {
    	writer.end();
    }

	//Other (check for business-logic, it should not remain here)

    /**
     * Getter for 'href', adds context-path unless it's a 'absolute URL' starting with 'http'.
     */
    public String getHref()
    {
        return href.startsWith("http")?href:(_req.getContextPath() + href);
    }

}
